﻿namespace ORM.Parser.Design.Format
{

    using System;
    using System.Collections.Generic;
    using System.Text;

    public class DdlFormatter : IFormatter
    {
        private const string Indent1 = "\n    ";
        private const string Indent2 = "\n      ";
        private const string Indent3 = "\n        ";

        public virtual string Format(string sql)
        {
            if (sql.ToLowerInvariant().StartsWith("create table"))
            {
                return this.FormatCreateTable(sql);
            }
            if (sql.ToLowerInvariant().StartsWith("alter table"))
            {
                return this.FormatAlterTable(sql);
            }
            if (sql.ToLowerInvariant().StartsWith("comment on"))
            {
                return this.FormatCommentOn(sql);
            }
            return ("\n    " + sql);
        }

        protected virtual string FormatAlterTable(string sql)
        {
            StringBuilder builder = new StringBuilder(60).Append("\n    ");
            IEnumerator<string> enumerator = new StringTokenizer(sql, " (,)'[]\"", true).GetEnumerator();
            bool flag = false;
            while (enumerator.MoveNext())
            {
                string current = enumerator.Current;
                if (IsQuote(current))
                {
                    flag = !flag;
                }
                else if (!flag && IsBreak(current))
                {
                    builder.Append("\n        ");
                }
                builder.Append(current);
            }
            return builder.ToString();
        }

        protected virtual string FormatCommentOn(string sql)
        {
            StringBuilder builder = new StringBuilder(60).Append("\n    ");
            IEnumerator<string> enumerator = new StringTokenizer(sql, " '[]\"", true).GetEnumerator();
            bool flag = false;
            while (enumerator.MoveNext())
            {
                string current = enumerator.Current;
                builder.Append(current);
                if (IsQuote(current))
                {
                    flag = !flag;
                }
                else if (!flag && "is".Equals(current))
                {
                    builder.Append("\n      ");
                }
            }
            return builder.ToString();
        }

        protected virtual string FormatCreateTable(string sql)
        {
            StringBuilder builder = new StringBuilder(60).Append("\n    ");
            IEnumerator<string> enumerator = new StringTokenizer(sql, "(,)'[]\"", true).GetEnumerator();
            int num = 0;
            bool flag = false;
            while (enumerator.MoveNext())
            {
                string current = enumerator.Current;
                if (IsQuote(current))
                {
                    flag = !flag;
                    builder.Append(current);
                }
                else
                {
                    if (flag)
                    {
                        builder.Append(current);
                        continue;
                    }
                    if (")".Equals(current))
                    {
                        num--;
                        if (num == 0)
                        {
                            builder.Append("\n    ");
                        }
                    }
                    builder.Append(current);
                    if (",".Equals(current) && (num == 1))
                    {
                        builder.Append("\n      ");
                    }
                    if ("(".Equals(current))
                    {
                        num++;
                        if (num == 1)
                        {
                            builder.Append("\n        ");
                        }
                    }
                }
            }
            return builder.ToString();
        }

        private static bool IsBreak(string token)
        {
            if ((!"drop".Equals(token) && !"add".Equals(token)) && (!"references".Equals(token) && !"foreign".Equals(token)))
            {
                return "on".Equals(token);
            }
            return true;
        }

        private static bool IsQuote(string token)
        {
            if ((!"\"".Equals(token) && !"`".Equals(token)) && (!"]".Equals(token) && !"[".Equals(token)))
            {
                return "'".Equals(token);
            }
            return true;
        }
    }
}

